﻿#pragma once
#include "qcontrol.h"

namespace micro
{

namespace gui
{



// A wrapper for the Treeview common control.
class QTreeControl : public QControl
{
    //_NO_COPY_PARAM( QTreeView, QControl );
public:
    // Constructor.
    QTreeControl()
    {
        ;
    }
    
    // Destructor.
    virtual ~QTreeControl()
    {
        ;
    }
    
    
    virtual bool Create( QWindow* pParent = nullptr, int id = 0, UINT style = 0 )
    {
        //TVS_HASLINES
        return  CreateBaseWindowEx( 0, GetWndClassName(), nullptr, style, QRect( 0, 0, 0, 0 ), pParent,  id );
    }
    
    
    
    virtual LPCTSTR GetWndClassName()
    {
        return WC_TREEVIEW;
    }
    
    bool SetItemText( HTREEITEM hItem, LPCTSTR lpszItem )
    {
        ASSERT( ::IsWindow( _window ) );
        return SetItem( hItem, TVIF_TEXT, lpszItem, 0, 0, 0, 0, 0 );
    }
    
    
    bool SetItem( HTREEITEM hItem, UINT nMask, LPCTSTR lpszItem, int nImage,
                  int nSelectedImage, UINT nState, UINT nStateMask, LPARAM lParam )
    {
        ASSERT( ::IsWindow( _window ) );
        TVITEM item = { 0 };
        item.hItem = hItem;
        item.mask = nMask;
        item.pszText = ( LPTSTR ) lpszItem;
        item.iImage = nImage;
        item.iSelectedImage = nSelectedImage;
        item.state = nState;
        item.stateMask = nStateMask;
        item.lParam = lParam;
        return toBool( SendMessage( TVM_SETITEM, 0, ( LPARAM )&item ) );
    }
    
    bool GetItemText( HTREEITEM hItem, LPTSTR lpstrText, int nLen ) const
    {
        ASSERT( ::IsWindow( _window ) );
        ASSERT( lpstrText != nullptr );
        
        TVITEM item = { 0 };
        item.hItem = hItem;
        item.mask = TVIF_TEXT;
        item.pszText = lpstrText;
        item.cchTextMax = nLen;
        
        return  toBool( ::SendMessage( _window, TVM_GETITEM, 0, ( LPARAM )&item ) );
    }
    
    HTREEITEM InsertItem( LPCTSTR lpszItem, HTREEITEM hParent, HTREEITEM hInsertAfter )
    {
        ASSERT( ::IsWindow( _window ) );
        return InsertItem( TVIF_TEXT, lpszItem, 0, 0, 0, 0, 0, hParent, hInsertAfter );
    }
    DWORD_PTR GetItemData( HTREEITEM hItem ) const
    {
        ASSERT( ::IsWindow( _window ) );
        TVITEM item = { 0 };
        item.hItem = hItem;
        item.mask = TVIF_PARAM;
        BOOL bRet = ( BOOL )::SendMessage( _window, TVM_GETITEM, 0, ( LPARAM )&item );
        return ( DWORD_PTR )( bRet ? item.lParam : 0 );
    }
    
    BOOL SetItemData( HTREEITEM hItem, DWORD_PTR dwData )
    {
        ASSERT( ::IsWindow( _window ) );
        return SetItem( hItem, TVIF_PARAM, nullptr, 0, 0, 0, 0, ( LPARAM )dwData );
    }
    
    
    
    
    // Create a drag image.
    inline HIMAGELIST CreateDragImage( HTREEITEM hItem ) const
    {
        ASSERT( _window ); // Must be valid.
        
        return TreeView_CreateDragImage( _window, hItem );
    }
    
    // Delete all items.
    inline BOOL DeleteAllItems()
    {
        ASSERT( _window ); // Must be valid.
        
        return TreeView_DeleteAllItems( _window );
    }
    
    // Delete a single item.
    inline BOOL DeleteItem( HTREEITEM hItem )
    {
        ASSERT( _window ); // Must be valid.
        
        return TreeView_DeleteItem( _window, hItem );
    }
    
    // Edit an item.
    inline HWND EditLabel( HTREEITEM hItem )
    {
        ASSERT( _window ); // Must be valid.
        
        return TreeView_EditLabel( _window, hItem );
    }
    
    // End editing the label.
    inline BOOL EndEditLabelNow( BOOL bCancel )
    {
        ASSERT( _window ); // Must be valid.
        
        return TreeView_EndEditLabelNow( _window, bCancel );
    }
    
    // Make sure an item is visible.
    inline BOOL EnsureVisible( HTREEITEM hItem )
    {
        ASSERT( _window ); // Must be valid.
        
        return TreeView_EnsureVisible( _window, hItem );
    }
    
    // Expand or collapse an item.
    inline BOOL Expand( HTREEITEM hItem, UINT nFlags )
    {
        ASSERT( _window ); // Must be valid.
        
        return TreeView_Expand( _window, hItem, nFlags );
    }
    
    // Get background color.
    inline COLORREF GetBkColor() const
    {
        ASSERT( _window ); // Must be valid.
        
        return TreeView_GetBkColor( _window );
    }
    
    // Get the item it's first child.
    inline HTREEITEM GetChild( HTREEITEM hItem ) const
    {
        ASSERT( _window ); // Must be valid.
        
        return TreeView_GetChild( _window, hItem );
    }
    
    // Get the number of items.
    inline UINT GetCount() const
    {
        ASSERT( _window ); // Must be valid.
        
        return TreeView_GetCount( _window );
    }
    
    // Get the DnD target.
    inline HTREEITEM GetDropHilight() const
    {
        ASSERT( _window ); // Must be valid.
        
        return TreeView_GetDropHilight( _window );
    }
    
    // Get the label edit control handle.
    inline HWND GetEditControl() const
    {
        ASSERT( _window ); // Must be valid.
        
        return TreeView_GetEditControl( _window );
    }
    
    // Get the first visible item.
    inline HTREEITEM GetFirstVisible() const
    {
        ASSERT( _window ); // Must be valid.
        
        return TreeView_GetFirstVisible( _window );
    }
    
    // Get the specific image list.
    inline HIMAGELIST GetImageList( int iImage ) const
    {
        ASSERT( _window ); // Must be valid.
        
        return TreeView_GetImageList( _window, iImage );
    }
    
    // Get the parent->child indentation.
    inline UINT GetIndent() const
    {
        ASSERT( _window ); // Must be valid.
        
        return TreeView_GetIndent( _window );
    }
    
    
    
    void SetIndent( UINT nIndent )
    {
        ASSERT( ::IsWindow( _window ) );
        ::SendMessage( _window, TVM_SETINDENT, nIndent, 0L );
    }
    
    // Get the insertion mark color.
    inline COLORREF GetInsertMarkColor() const
    {
        ASSERT( _window ); // Must be valid.
        
        return TreeView_GetInsertMarkColor( _window );
    }
    
    // Get the incremental search string.
    inline UINT GetISearchString( LPTSTR pszString ) const
    {
        ASSERT( _window ); // Must be valid.
        
        return TreeView_GetISearchString( _window, pszString );
    }
    
    // Get item info.
    inline BOOL GetItem( TVITEM& item ) const
    {
        ASSERT( _window ); // Must be valid.
        
        return TreeView_GetItem( _window, &item );
    }
    
    // Get the height of the items.
    inline int GetItemHeight() const
    {
        ASSERT( _window ); // Must be valid.
        
        return TreeView_GetItemHeight( _window );
    }
    
    // Get the item bounds.
    inline BOOL GetItemRect( HTREEITEM hItem, LPRECT pRect, BOOL bOnlyLabel = FALSE )
    {
        ASSERT( _window ); // Must be valid.
        
        return TreeView_GetItemRect( _window, hItem, pRect, bOnlyLabel );
    }
    
    // Get the last visible item.
    inline HTREEITEM GetLastVisible() const
    {
        ASSERT( _window ); // Must be valid.
        
        return TreeView_GetLastVisible( _window );
    }
    
    // Get the next item.
    inline HTREEITEM GetNextItem( HTREEITEM hItem, UINT nFlags ) const
    {
        ASSERT( _window ); // Must be valid.
        
        return TreeView_GetNextItem( _window, hItem, nFlags );
    }
    
    // Get the next sibling.
    inline HTREEITEM GetNextSibling( HTREEITEM hItem ) const
    {
        ASSERT( _window ); // Must be valid.
        
        return TreeView_GetNextSibling( _window, hItem );
    }
    
    // Get the next visible item.
    inline HTREEITEM GetNextVisible( HTREEITEM hItem ) const
    {
        ASSERT( _window ); // Must be valid.
        
        return TreeView_GetNextVisible( _window, hItem );
    }
    
    // Get the parent.
    inline HTREEITEM GetParentItem( HTREEITEM hItem ) const
    {
        ASSERT( _window ); // Must be valid.
        
        return TreeView_GetParent( _window, hItem );
    }
    
    // Get the previous sibling.
    inline HTREEITEM GetPrevSibling( HTREEITEM hItem ) const
    {
        ASSERT( _window ); // Must be valid.
        
        return TreeView_GetPrevSibling( _window, hItem );
    }
    
    // Get the previous visible item.
    inline HTREEITEM GetPrevVisible( HTREEITEM hItem ) const
    {
        ASSERT( _window ); // Must be valid.
        
        return TreeView_GetPrevVisible( _window, hItem );
    }
    
    // Get the root item.
    inline HTREEITEM GetRoot() const
    {
        ASSERT( _window ); // Must be valid.
        
        return TreeView_GetRoot( _window );
    }
    
    // Get the maximum scroll time.
    inline UINT GetScrollTime() const
    {
        ASSERT( _window ); // Must be valid.
        
        return TreeView_GetScrollTime( _window );
    }
    
    // Get the currently selected item.
    inline HTREEITEM GetSelection() const
    {
        ASSERT( _window ); // Must be valid.
        
        return TreeView_GetSelection( _window );
    }
    
    // Get the text color.
    inline COLORREF GetTextColor() const
    {
        ASSERT( _window ); // Must be valid.
        
        return TreeView_GetTextColor( _window );
    }
    
    // Get the tooltip control.
    inline HWND GetToolTips() const
    {
        ASSERT( _window ); // Must be valid.
        
        return TreeView_GetToolTips( _window );
    }
    
    // Get unicode flag.
    inline BOOL GetUnicodeFormat() const
    {
        ASSERT( _window ); // Must be valid.
        
        return TreeView_GetUnicodeFormat( _window );
    }
    
    // Get number of visible items.
    inline UINT GetVisibleCount() const
    {
        ASSERT( _window ); // Must be valid.
        
        return TreeView_GetVisibleCount( _window );
    }
    
    // Hit test the control.
    inline HTREEITEM HitTest( TVHITTESTINFO& htinfo ) const
    {
        ASSERT( _window ); // Must be valid.
        
        return TreeView_HitTest( _window, &htinfo );
    }
    
    // Insert an item.
    inline HTREEITEM InsertItem( TVINSERTSTRUCT& istruct )
    {
        ASSERT( _window ); // Must be valid.
        
        return TreeView_InsertItem( _window, &istruct );
    }
    
    // Select an item.
    inline BOOL Select( HTREEITEM hItem, UINT nFlags )
    {
        ASSERT( _window ); // Must be valid.
        
        return TreeView_Select( _window, hItem, nFlags );
    }
    
    // Redraw item to a DnD target.
    inline BOOL SelectDropTarget( HTREEITEM hItem )
    {
        ASSERT( _window ); // Must be valid.
        
        return TreeView_SelectDropTarget( _window, hItem );
    }
    
    // Select the item.
    inline BOOL SelectItem( HTREEITEM hItem )
    {
        ASSERT( _window ); // Must be valid.
        
        return TreeView_SelectItem( _window, hItem );
    }
    
    // Setup background color.
    inline COLORREF SetBkColor( COLORREF crColor )
    {
        ASSERT( _window ); // Must be valid.
        
        return TreeView_SetBkColor( _window, crColor );
    }
    
    // Select the item and make it the first visible item.
    inline BOOL SelectSetFirstVisible( HTREEITEM hItem )
    {
        ASSERT( _window ); // Must be valid.
        
        return TreeView_SelectSetFirstVisible( _window, hItem );
    }
    
    // Set the specific image list.
    inline HIMAGELIST SetImageList( HIMAGELIST hImageList, int iImage )
    {
        ASSERT( _window ); // Must be valid.
        
        return TreeView_SetImageList( _window, hImageList, iImage );
    }
    
    // Set parent->child indention.
    inline void SetIndent( int iIndent )
    {
        ASSERT( _window ); // Must be valid.
        
        TreeView_SetIndent( _window, iIndent );
    }
    
    // Set insertion mark.
    inline BOOL SetInsertMark( HTREEITEM hItem, BOOL bAfter )
    {
        ASSERT( _window ); // Must be valid.
        
        return TreeView_SetInsertMark( _window, hItem, bAfter );
    }
    
    // Set insertion mark color.
    inline COLORREF SetInsertMarkColor( COLORREF crColor )
    {
        ASSERT( _window ); // Must be valid.
        
        return TreeView_SetInsertMarkColor( _window, crColor );
    }
    
    // Set item info.
    inline BOOL SetItem( TVITEM& item )
    {
        ASSERT( _window ); // Must be valid.
        
        return ( BOOL )TreeView_SetItem( _window, &item );
    }
    
    // Set item height.
    inline int SetItemHeight( int cy )
    {
        ASSERT( _window ); // Must be valid.
        
        return TreeView_SetItemHeight( _window, cy );
    }
    
    // Set the maximum scroll time.
    inline UINT SetScrollTime( UINT nScrollTime )
    {
        ASSERT( _window ); // Must be valid.
        
        return TreeView_SetScrollTime( _window, nScrollTime );
    }
    
    // Set the text color.
    inline COLORREF SetTextColor( COLORREF crColor )
    {
        ASSERT( _window ); // Must be valid.
        
        return TreeView_SetTextColor( _window, crColor );
    }
    
    // Set the tooltip control.
    inline HWND SetToolTips( HWND hWndTooltip )
    {
        ASSERT( _window ); // Must be valid.
        
        return TreeView_SetToolTips( _window, hWndTooltip );
    }
    
    // Set the unicode flag.
    inline BOOL SetUnicodeFormat( BOOL bUnicode )
    {
        ASSERT( _window ); // Must be valid.
        
        return TreeView_SetUnicodeFormat( _window, bUnicode );
    }
    
    // Sort children.
    inline BOOL SortChildren( HTREEITEM hItem, BOOL bRecurse = FALSE )
    {
        ASSERT( _window ); // Must be valid.
        
        return TreeView_SortChildren( _window, hItem, bRecurse );
    }
    
    // Sort children with callback.
    inline BOOL SortChildrenCB( TVSORTCB& sort, BOOL bRecurse = FALSE )
    {
        ASSERT( _window ); // Must be valid.
        
        return TreeView_SortChildrenCB( _window, &sort, bRecurse );
    }
    
    HTREEITEM InsertItem( LPTVINSERTSTRUCT lpInsertStruct )
    {
        ASSERT( ::IsWindow( _window ) );
        return ( HTREEITEM )::SendMessage( _window, TVM_INSERTITEM, 0, ( LPARAM )lpInsertStruct );
    }
    
    HTREEITEM InsertItem( LPCTSTR lpszItem, int nImage,
                          int nSelectedImage, HTREEITEM hParent, HTREEITEM hInsertAfter )
    {
        ASSERT( ::IsWindow( _window ) );
        return InsertItem( TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE, lpszItem, nImage, nSelectedImage, 0, 0, 0, hParent, hInsertAfter );
    }
    
    
    
    HTREEITEM InsertItem( UINT nMask, LPCTSTR lpszItem, int nImage,
                          int nSelectedImage, UINT nState, UINT nStateMask, LPARAM lParam,
                          HTREEITEM hParent, HTREEITEM hInsertAfter )
    {
        ASSERT( ::IsWindow( _window ) );
        TVINSERTSTRUCT tvis = { 0 };
        tvis.hParent = hParent;
        tvis.hInsertAfter = hInsertAfter;
        tvis.item.mask = nMask;
        tvis.item.pszText = ( LPTSTR ) lpszItem;
        tvis.item.iImage = nImage;
        tvis.item.iSelectedImage = nSelectedImage;
        tvis.item.state = nState;
        tvis.item.stateMask = nStateMask;
        tvis.item.lParam = lParam;
        return ( HTREEITEM )::SendMessage( _window, TVM_INSERTITEM, 0, ( LPARAM )&tvis );
    }
    
    
    
    
    
    
    
    HTREEITEM GetChildItem( HTREEITEM hItem ) const
    {
        ASSERT( ::IsWindow( _window ) );
        return ( HTREEITEM )::SendMessage( _window, TVM_GETNEXTITEM, TVGN_CHILD, ( LPARAM )hItem );
    }
    
    HTREEITEM GetNextSiblingItem( HTREEITEM hItem ) const
    {
        ASSERT( ::IsWindow( _window ) );
        return ( HTREEITEM )::SendMessage( _window, TVM_GETNEXTITEM, TVGN_NEXT, ( LPARAM )hItem );
    }
    
    HTREEITEM GetPrevSiblingItem( HTREEITEM hItem ) const
    {
        ASSERT( ::IsWindow( _window ) );
        return ( HTREEITEM )::SendMessage( _window, TVM_GETNEXTITEM, TVGN_PREVIOUS, ( LPARAM )hItem );
    }
    
    
    
    HTREEITEM GetFirstVisibleItem() const
    {
        ASSERT( ::IsWindow( _window ) );
        return ( HTREEITEM )::SendMessage( _window, TVM_GETNEXTITEM, TVGN_FIRSTVISIBLE, 0L );
    }
    
    HTREEITEM GetNextVisibleItem( HTREEITEM hItem ) const
    {
        ASSERT( ::IsWindow( _window ) );
        return ( HTREEITEM )::SendMessage( _window, TVM_GETNEXTITEM, TVGN_NEXTVISIBLE, ( LPARAM )hItem );
    }
    
    HTREEITEM GetPrevVisibleItem( HTREEITEM hItem ) const
    {
        ASSERT( ::IsWindow( _window ) );
        return ( HTREEITEM )::SendMessage( _window, TVM_GETNEXTITEM, TVGN_PREVIOUSVISIBLE, ( LPARAM )hItem );
    }
    
    HTREEITEM GetSelectedItem() const
    {
        ASSERT( ::IsWindow( _window ) );
        return ( HTREEITEM )::SendMessage( _window, TVM_GETNEXTITEM, TVGN_CARET, 0L );
    }
    
    HTREEITEM GetDropHilightItem() const
    {
        ASSERT( ::IsWindow( _window ) );
        return ( HTREEITEM )::SendMessage( _window, TVM_GETNEXTITEM, TVGN_DROPHILITE, 0L );
    }
    
    HTREEITEM GetRootItem() const
    {
        ASSERT( ::IsWindow( _window ) );
        return ( HTREEITEM )::SendMessage( _window, TVM_GETNEXTITEM, TVGN_ROOT, 0L );
    }
    
protected:
    // Overidables.
    virtual LRESULT OnBeginDrag( LPNMTREEVIEW pTreeView, BOOL& bNotifyParent )
    {
        return 0;
    }
    
    virtual LRESULT OnBeginLabelEdit( LPNMTVDISPINFO pDispInfo, BOOL& bNotifyParent )
    {
        return FALSE;
    }
    
    virtual LRESULT OnBeginRDrag( LPNMTREEVIEW pTreeView, BOOL& bNotifyParent )
    {
        return 0;
    }
    
    virtual LRESULT OnDeleteItem( LPNMTREEVIEW pTreeView, BOOL& bNotifyParent )
    {
        return 0;
    }
    
    virtual LRESULT OnEndLabelEdit( LPNMTVDISPINFO pDispInfo, BOOL& bNotifyParent )
    {
        return pDispInfo->item.pszText ? TRUE : FALSE;
    }
    
    virtual LRESULT OnGetDispInfo( LPNMTVDISPINFO pDispInfo, BOOL& bNotifyParent )
    {
        return 0;
    }
    
    virtual LRESULT OnGetInfoTip( LPNMTVGETINFOTIP pInfoTip, BOOL& bNotifyParent )
    {
        return 0;
    }
    
    virtual LRESULT OnItemExpanded( LPNMTREEVIEW pTreeView, BOOL& bNotifyParent )
    {
        return 0;
    }
    
    virtual LRESULT OnItemExpanding( LPNMTREEVIEW pTreeView, BOOL& bNotifyParent )
    {
        return FALSE;
    }
    
    virtual LRESULT OnKeyDown( LPNMTVKEYDOWN pKeyDown, BOOL& bNotifyParent )
    {
        return FALSE;
    }
    
    virtual LRESULT OnSelChanged( LPNMTREEVIEW pTreeView, BOOL& bNotifyParent )
    {
        return 0;
    }
    
    virtual LRESULT OnSelChanging( LPNMTREEVIEW pTreeView, BOOL& bNotifyParent )
    {
        return FALSE;
    }
    
    virtual LRESULT OnSetDispInfo( LPNMTVDISPINFO pDispInfo, BOOL& bNotifyParent )
    {
        return 0;
    }
    
    virtual LRESULT OnSingleExpand( LPNMTREEVIEW pTreeView, BOOL& bNotifyParent )
    {
        return 0;
    }
    
    // Reflected notification handler which will call
    // the virtual notification handlers.
    virtual LRESULT OnReflectedNotify( LPNMHDR pNMHDR, BOOL& bNotifyParent )
    {
        // Evaluate notification code.
        switch ( pNMHDR->code )
        {
            case	TVN_BEGINDRAG:
                return OnBeginDrag( ( LPNMTREEVIEW )pNMHDR, bNotifyParent );
                
            case	TVN_BEGINLABELEDIT:
                return OnBeginLabelEdit( ( LPNMTVDISPINFO )pNMHDR, bNotifyParent );
                
            case	TVN_BEGINRDRAG:
                return OnBeginRDrag( ( LPNMTREEVIEW )pNMHDR, bNotifyParent );
                
            case	TVN_DELETEITEM:
                return OnDeleteItem( ( LPNMTREEVIEW )pNMHDR, bNotifyParent );
                
            case	TVN_ENDLABELEDIT:
                return OnEndLabelEdit( ( LPNMTVDISPINFO )pNMHDR, bNotifyParent );
                
            case	TVN_GETDISPINFO:
                return OnGetDispInfo( ( LPNMTVDISPINFO )pNMHDR, bNotifyParent );
                
            case	TVN_GETINFOTIP:
                return OnGetInfoTip( ( LPNMTVGETINFOTIP )pNMHDR, bNotifyParent );
                
            case	TVN_ITEMEXPANDED:
                return OnItemExpanded( ( LPNMTREEVIEW )pNMHDR, bNotifyParent );
                
            case	TVN_ITEMEXPANDING:
                return OnItemExpanding( ( LPNMTREEVIEW )pNMHDR, bNotifyParent );
                
            case	TVN_KEYDOWN:
                return OnKeyDown( ( LPNMTVKEYDOWN )pNMHDR, bNotifyParent );
                
            case	TVN_SELCHANGED:
                return OnSelChanged( ( LPNMTREEVIEW )pNMHDR, bNotifyParent );
                
            case	TVN_SELCHANGING:
                return OnSelChanging( ( LPNMTREEVIEW )pNMHDR, bNotifyParent );
                
            case	TVN_SETDISPINFO:
                return OnSetDispInfo( ( LPNMTVDISPINFO )pNMHDR, bNotifyParent );
                
            case	TVN_SINGLEEXPAND:
                return OnSingleExpand( ( LPNMTREEVIEW )pNMHDR, bNotifyParent );
        }
        
        // Call the base class.
        return QControl::OnReflectedNotify( pNMHDR, bNotifyParent );
    }
    
    
};





}//gui

}//micro